﻿#region << 版 本 注 释 >>
/*----------------------------------------------------------------
 * 版权所有 (c) 2022 北京超维景生物科技有限公司 保留所有权利。
 * 
 * 创建者：huangyang
 * 电子邮箱：huangyang@tvscope.cn
 * 创建时间：2023/2/28 16:34:40
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion << 版 本 注 释 >>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImageK.IO
{
	/**
     * A class for reading arbitrary numbers of bits from a byte array.
     * @author Eric Kjellman egkjellman at wisc.edu
     */
    public class BitBuffer
    {

        private int currentByte;
        private int currentBit;
        private byte[] byteBuffer;
        private int eofByte;
        private int[] backMask;
        private int[] frontMask;
        private bool eofFlag;

        public BitBuffer(byte[] byteBuffer)
        {
            this.byteBuffer = byteBuffer;
            currentByte = 0;
            currentBit = 0;
            eofByte = byteBuffer.Length;
            backMask = new int[] {0x0000, 0x0001, 0x0003, 0x0007,
                0x000F, 0x001F, 0x003F, 0x007F};
            frontMask = new int[] {0x0000, 0x0080, 0x00C0, 0x00E0,
                0x00F0, 0x00F8, 0x00FC, 0x00FE};
        }

        public int getBits(int bitsToRead)
        {
            if (bitsToRead == 0)
                return 0;
            if (eofFlag)
                return -1; // Already at end of file
            int toStore = 0;
            while (bitsToRead != 0 && !eofFlag)
            {
                if (bitsToRead >= 8 - currentBit)
                {
                    if (currentBit == 0)
                    { // special
                        toStore = toStore << 8;
                        int cb = ((int)byteBuffer[currentByte]);
                        toStore += (cb < 0 ? (int)256 + cb : (int)cb);
                        bitsToRead -= 8;
                        currentByte++;
                    }
                    else
                    {
                        toStore = toStore << (8 - currentBit);
                        toStore += ((int)byteBuffer[currentByte]) & backMask[8 - currentBit];
                        bitsToRead -= (8 - currentBit);
                        currentBit = 0;
                        currentByte++;
                    }
                }
                else
                {
                    toStore = toStore << bitsToRead;
                    int cb = ((int)byteBuffer[currentByte]);
                    cb = (cb < 0 ? (int)256 + cb : (int)cb);
                    toStore += ((cb) & (0x00FF - frontMask[currentBit])) >> (8 - (currentBit + bitsToRead));
                    currentBit += bitsToRead;
                    bitsToRead = 0;
                }
                if (currentByte == eofByte)
                {
                    eofFlag = true;
                    return toStore;
                }
            }
            return toStore;
        }

    }
}
